using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using Uber.Core.Model;
using Uber.Core.Repository;

namespace Uber.Data
{
    public interface IDbContextFactory
    {
        DbContext GetContext();
    }

    public class DbContextFactory : IDbContextFactory
    {
        private readonly DbContext c;
        public DbContextFactory()
        {
            c = new Db();
        }

        public DbContext GetContext()
        {
            return c;
        }
    }

    public class Db : DbContext
    {
        public DbSet<Account> Accounts { get; set; }
        public DbSet<AweOid> AweOids { get; set; }
        public DbSet<Recover> Recovers { get; set; }
        public DbSet<Post> Posts { get; set; }
        public DbSet<Comment> Comments { get; set; }
        public DbSet<Notification> Notifications { get; set; }
        public DbSet<Product> Products { get; set; }
        public DbSet<ProductVersion> ProductVersions { get; set; }
        public DbSet<Purchase> Purchases { get; set; }
        public DbSet<License> Licenses { get; set; }
    }

    public class Repo<T> : IRepo<T> where T : Entity, new()
    {
        protected readonly DbContext c;

        public Repo(Db f)
        {
            c = f;
        }

        public T Create()
        {
            return c.Set<T>().Create();
        }

        public void Save()
        {
            c.SaveChanges();
        }

        public void Add(T o)
        {
            c.Set<T>().Add(o);
        }

        public void Insert(IEnumerable<T> oo)
        {
            foreach (var o in oo)
                Add(o);
        }

        public T Get(long id)
        {
            return c.Set<T>().Find(id);
        }
    
        public virtual IEnumerable<T> Where(Expression<Func<T, bool>> predicate)
        {
            return c.Set<T>().Where(predicate);
        }

        public virtual IEnumerable<T> GetAll()
        {
            return c.Set<T>();
        }

        public void Remove(T o)
        {
            c.Set<T>().Remove(o);
        }

        public void Delete(long id)
        {
            c.Set<T>().Remove(Get(id));
        }
    }

    public class UniRepo : IUniRepo
    {
        private readonly DbContext c;

        public UniRepo(Db a)
        {
            c = a;
        }

        public void Add<T>(T o) where T : Entity
        {
            c.Set<T>().Add(o);
        }

        public T Create<T>() where T : class
        {
            return c.Set<T>().Create();
        }

        public void Save()
        {
            c.SaveChanges();
        }

        public T Get<T>(long id) where T : Entity
        {
            return c.Set<T>().Find(id);
        }

        public IEnumerable<T> GetAll<T>() where T : Entity
        {
            return c.Set<T>();
        }

        public virtual IEnumerable<T> Where<T>(Expression<Func<T, bool>> predicate) where T: Entity
        {
            return c.Set<T>().Where(predicate);
        }
    }
}